package com.unitd.frame.sso.service.sso;

import com.unitd.frame.sso.common.token.AuthToken;
import com.unitd.frame.sso.common.token.Token;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @desc SSO 单点登录服务接口
 * @filename ISSOService.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2016/10/14
 */
public interface ISSOService {

	/* ************************** 登录/登出/统计相关处理方法 ************************** */
	/**
	 * @desc 在当前访问域下,设置当前登录用户的 登录 Cookie
	 * request.setAttribute(SSOConfig.SSO_COOKIE_MAXAGE, -1);
	 * 可以设置 Cookie 超时时间 ,默认读取配置文件数据
	 * -1 浏览器关闭时自动删除 0 立即删除 120 表示Cookie有效期2分钟(以秒为单位)
	 * @param request  http请求对象
	 * @param response http响应对象
	 * @param token    SSO登录票据对象
	 */
	void setSSOCookie(HttpServletRequest request, HttpServletResponse response, Token token);

	/**
	 * @desc 当前访问域下设置登录Cookie 设置防止伪造SESSIONID攻击
	 * @param request  http请求对象
	 * @param response http相应对象
	 */
	void authSSOCookie(HttpServletRequest request, HttpServletResponse response, Token token);

	/**
	 * @desc 获取当前通过SSO登录的在线人数(总数)
	 * @param request 查询请求
	 * @return 当前通过SSO登录的在线人数
	 */
	String getLoginCount(HttpServletRequest request);

	/**
	 * @desc 退出SSO 登录
	 * @param request  http请求对象
	 * @param response http相应对象
	 * @throws IOException
	 */
	void logout(HttpServletRequest request, HttpServletResponse response) throws IOException;

	/**
	 * @desc 根据指定的用户 ID 踢出该登录用户,退出当前系统
	 * @param userId 用户ID
	 * @return boolean 踢出登录成功与否
	 */
	boolean kickLogin(Object userId);

	/**
	 * @desc 退出登录并清理当前登录状态;清理 Cookie、缓存、统计、等数据,但不进行重定向
	 * @param request  http请求对象
	 * @param response http相应对象
	 * @return boolean 退出登录成功与否
	 */
	boolean clearLogin(HttpServletRequest request, HttpServletResponse response);

	/**
	 * @desc 退出登录并清理当前登录状态;清理 Cookie、缓存、统计、等数据;
	 * 完成后,重定向到sso.properties 配置文件中的属性 sso.login.url 指定的登录URL地址
	 * 一般情况下,使用此方法作为登出处理
	 * @param request  http请求对象
	 * @param response http相应对象
	 * @throws IOException
	 */
	void clearRedirectLogin(HttpServletRequest request, HttpServletResponse response) throws IOException;


	/* ************************** 客户端处理Token相关方法 ************************** */
	/**
	 * @desc 获取当前请求 Token(从 Cookie中解密 token )
	 * 使用场景:拦截器下使用; 非拦截器建议使用 attrToken 减少二次解密
	 * @param request http请求对象
	 * @return Token {@link Token}
	 */
	Token getToken(HttpServletRequest request);

	/**
	 * @desc 从请求中获取当前请求
	 * 由于在登录拦截器中已存放了解密之后的请求Token信息,所以在这里这几获取即可,防止二次解密
	 * 此属性在过滤器拦截器中设置,业务系统中调用有效
	 * @param request 访问请求
	 * @return 当前请求的具体 Token {@link Token}
	 */
	<T extends Token> T attrToken(HttpServletRequest request);


	/* ************************** 跨域处理相关方法 ************************** */
	/**
	 * @desc 根据RSA私钥生成对应的跨域询问密文(公钥,用于跨域处理)
	 * @param request  http请求对象
	 * @param response http相应对象
	 * @param privateKey 私钥
	 * @return 跨域密文
	 */
	AuthToken askCiphertext(HttpServletRequest request, HttpServletResponse response, String privateKey);

	/**
	 * @desc 根据请求的询问密文生成对应的跨域回复密文(公钥,用于跨域处理)
	 * @param askData 询问密文
	 * @return AuthToken {@link AuthToken}
	 */
	AuthToken replyCiphertext(HttpServletRequest request, String askData);

	/**
	 * @desc 验证跨域回复密文的有效性,如果成功则返回绑定的用户ID 等信息
	 * @param request   http请求对象
	 * @param response  http相应对象
	 * @param replyData 回复密文
	 * @param atPk      RSA 公钥 (业务系统公钥,验证authToken签名)
	 * @param ssoPrk    RSA 公钥 (SSO 回复密文公钥验证签名)
	 * @return AuthToken {@link AuthToken}
	 */
	AuthToken ok(HttpServletRequest request, HttpServletResponse response, String replyData, String atPk, String ssoPrk);
}